home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / quicktime / effects / dimmer2effect.win / effect.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  27.2 KB  |  981 lines

  1. /*
  2.     Dimmer2Effect.c - a sample QuickTime video effect.
  3.     
  4.     This effect uses a single source as input, and renders that source with
  5.     a dim value that starts at full on, and ramps to full off.  This isn't very
  6.     useful as a real effect, but shows instead how to create an effect.
  7.     
  8.     READ THIS PARAGRAPH BEFORE DOING ANYTHING ELSE IN THIS FILE:
  9.     To find things to change to implement your effect, seach for *** CHANGE ***.  
  10.     Code that will require modification is bracketted by CHANGE/END CHANGE.
  11.     
  12.     There are eleven places to change code, and one place where you write new
  13.     code that implements your actual effect.  MAKE SURE YOU LOOK AT ALL OF THEM.
  14.     
  15.     *IMPORTANT*
  16.     
  17.     You MUST also ensure that the Effect.r file is kept in sync with this code.
  18.     In particular it is very important that you update the 'atms' resource
  19.     description so that the parameters of your effect are correctly described.
  20.     Full details of the format of the 'atms' resource can be found in the Effects
  21.     chapter of the QT 3.0 documentation
  22.     
  23.     ALSO PLEASE NOTE THAT THE LINK WARNING ABOUT THE COMPONENT DISPATCH ENTRY POINT
  24.     NOT BEING A ROUTINE DESCRIPTOR IS NORMAL AND CAN BE IGNORED!
  25.     
  26.     written by Tom Dowdy and Dan Crow
  27.     copyright © 1997-1998 Apple Computer, Inc.
  28.     All rights reserved.
  29. */
  30.  
  31.  
  32. // --------------------------------------------------------------------------------------
  33. // INCLUDES
  34. // --------------------------------------------------------------------------------------
  35.  
  36. #include <MacMemory.h>
  37. #include <Resources.h>
  38. #include <Quickdraw.h>    
  39. #include <QDOffscreen.h>
  40. #include <OSUtils.h>
  41. #include <Errors.h>
  42. #include <FixMath.h>
  43. #include <Movies.h>
  44. #include <Endian.h>
  45. #include <ImageCodec.h>
  46.  
  47. #include "EffectDefinitions.h"
  48.  
  49.  
  50. #if PRAGMA_STRUCT_ALIGN
  51.     #pragma options align=mac68k
  52. #endif
  53.  
  54. #include "EffectUtilities.h"
  55.  
  56.  
  57. // --------------------------------------------------------------------------------------
  58. // INTERNAL DEFINES
  59. // --------------------------------------------------------------------------------------
  60.  
  61. // *** CHANGE *** This defines the number of frames that can be queued for
  62. // asynchronous rendering by this effect.  The value 0 indicates the effect
  63. // runs synchronously.
  64. #define kMaxAsyncFrames        0
  65. // *** END CHANGE ***
  66.  
  67. // *** CHANGE *** Change if your effect accepts multiple sources.  This value
  68. // is the maximum number of sources this effect operates on.
  69. #define    kMaxSources            2
  70. // *** END CHANGE ***
  71.  
  72. // --------------------------------------------------------------------------------------
  73. // INTERNAL TYPEDEFS
  74. // --------------------------------------------------------------------------------------
  75.  
  76. // Structure used to store inforation about each source
  77. typedef struct SourceRecord {                        
  78.     CDSequenceDataSourcePtr    src;
  79.     void                    *srcBaseAddr;
  80.     long                    srcRowBytes;
  81. } SourceRecord;
  82.  
  83. // This is the structure used to store information for drawing a single frame of the effect
  84. typedef struct BlitGlobals {                            
  85.     SourceRecord        sources[kMaxSources];    // inputs
  86.  
  87.     void                *dstBaseAddr;            // output base address
  88.     long                dstRowBytes;            // output row bytes
  89.     long                height;                    // output height
  90.     long                width;                    // output width
  91.     short                destDepth;                // output depth
  92.     OSType                dstPixelFormat;            // output pixel format
  93.     
  94.     // *** CHANGE *** Here is where we store values relating to a single frame
  95.     // of the effect.  These are the parameters to the effect, modified by the
  96.     // percentage into the effect which we are.
  97.     
  98.     long                direction;
  99.     short                dimValue;                // dimming value, from 0 to 255
  100.     
  101.     // *** END CHANGE ***
  102. } BlitGlobals;
  103.  
  104.  
  105. // global data per instance. This holds data for the entire effect as it runs its course.
  106. typedef struct EffectGlobals
  107.     {
  108.     ComponentInstance    self;        // ourselves
  109.     ComponentInstance    target;        // top of the calling chain
  110.     ComponentInstance    delegate;    // if we can't handle an effect, this one can
  111.     
  112.     BlitGlobals            blitter;    // information for drawing the data
  113.     OSType                **wantedDestinationPixelTypeH;
  114.     
  115.     #if kMaxAsyncFrames > 0
  116.         volatile short    asyncCount;    // number of outstanding frames we have        
  117.     #endif
  118.     
  119.     // parameter/source/dest seed tracking
  120.     long                        initialized;
  121.     long                        frameNumber;            
  122.     long                        virtualDuration;
  123.     long                        majorSourceChangeSeed;
  124.     
  125.     TweenGlobals                tweenGlobals;
  126.  
  127.     // *** CHANGE *** PLACE PARAMETERS FOR YOUR EFFECT HERE
  128.     
  129.     long                        direction;    // direction of blit.  0 for dim to bright, 255 for bright to dim
  130.         
  131.     TweenContainerRecord        percentage;
  132.     
  133.     // *** END CHANGE ***
  134. } EffectGlobals;
  135.  
  136. // --------------------------------------------------------------------------------------
  137. // DISPATCHER
  138. // --------------------------------------------------------------------------------------
  139. /************************************************************************************ 
  140.  *    This is the main dispatcher for our codec. All calls from the codec manager
  141.  *    will come through here, with a unique selector and corresponding parameter block.
  142.  *
  143.  *    This routine must be first in the code segment of the codec component.
  144.  *
  145.  *    We use the normal dispatcher rather than the codec dispatcher as we need to
  146.  *    implement the extra effects routines on top of the codec ones.
  147.  */
  148. /************************************************************************************/
  149. // Begin Dispatch Stuff
  150.  
  151. // Used by Component Dispatch Helper to call our routines
  152. #define CALLCOMPONENT_BASENAME()        EffectsFrame
  153. #define    CALLCOMPONENT_GLOBALS()            EffectGlobals * storage
  154.  
  155. // Used by Type's .k.h to create prototypes for our routines
  156. #define    IMAGECODEC_BASENAME()            CALLCOMPONENT_BASENAME()
  157. #define    IMAGECODEC_GLOBALS()            CALLCOMPONENT_GLOBALS()
  158.  
  159. // Used by SubType's .k.h to create prototypes for our routines
  160. #define    IMAGECODECEFFECT_BASENAME()        CALLCOMPONENT_BASENAME()
  161. #define    IMAGECODECEFFECT_GLOBALS()        CALLCOMPONENT_GLOBALS()
  162.  
  163. // Other defines for Component Dispatch Helper
  164. #define COMPONENT_DISPATCH_FILE            "EffectDispatch.h"    // describes what to dispatch
  165. #define    GET_DELEGATE_COMPONENT()        (storage->delegate)    // how to find delegate component
  166.  
  167. #define COMPONENT_UPP_SELECT_ROOT()        ImageCodec            // root for Type's UPP_PREFIX and SELECT_PREFIX        
  168.  
  169. #include "Components.k.h"                // StdComponent's .k.h
  170. #include "ImageCodec.k.h"                // Type's .k.h
  171. #include "ComponentDispatchHelper.c"    // make our dispatcher and cando
  172.  
  173. // End Dispatch Stuff
  174. /************************************************************************************/
  175.  
  176. // --------------------------------------------------------------------------------------
  177. // MULTIPLE BIT-DEPTH AND PIXEL FORMATS
  178. //    For clarity/reuse sake, the drawing code is being kept separate from the component
  179. //    interface code.
  180. // --------------------------------------------------------------------------------------
  181.  
  182.  
  183. // 16BE555
  184. #define EffectFilter16 EffectFilter16BE555
  185. #define srcIs16BE555 1
  186. #define dstIs16BE555 1
  187. #include "EffectFilter16.c"
  188. #undef EffectFilter16
  189. #undef srcIs16BE555
  190. #undef dstIs16BE555
  191.  
  192. #if NON_MAC_PIXEL_FORMATS
  193. // 16LE555
  194. #define EffectFilter16 EffectFilter16LE555
  195. #define srcIs16LE555 1
  196. #define dstIs16LE555 1
  197. #include "EffectFilter16.c"
  198. #undef EffectFilter16
  199. #undef srcIs16LE555
  200. #undef dstIs16LE555
  201.  
  202. // 16LE565
  203. #define EffectFilter16 EffectFilter16LE565
  204. #define srcIs16LE565 1
  205. #define dstIs16LE565 1
  206. #include "EffectFilter16.c"
  207. #undef EffectFilter16
  208. #undef srcIs16LE565
  209. #undef dstIs16LE565
  210.  
  211. #endif
  212.  
  213. // 32ARGB
  214. #define EffectFilter32 EffectFilter32ARGB
  215. #define srcIs32ARGB 1
  216. #define dstIs32ARGB 1
  217. #include "EffectFilter32.c"
  218. #undef EffectFilter32
  219. #undef srcIs32ARGB
  220. #undef dstIs32ARGB
  221. #if NON_MAC_PIXEL_FORMATS
  222. // 32BGRA
  223. #define EffectFilter32 EffectFilter32BGRA
  224. #define srcIs32BGRA 1
  225. #define dstIs32BGRA 1
  226. #include "EffectFilter32.c"
  227. #undef EffectFilter32
  228. #undef srcIs32BGRA
  229. #undef dstIs32BGRA
  230. // 32RGBA
  231. #define EffectFilter32 EffectFilter32RGBA
  232. #define srcIs32RGBA 1
  233. #define dstIs32RGBA 1
  234. #include "EffectFilter32.c"
  235. #undef EffectFilter32
  236. #undef srcIs32RGBA
  237. #undef dstIs32RGBA
  238. // 32ABGR
  239. #define EffectFilter32 EffectFilter32ABGR
  240. #define srcIs32ABGR 1
  241. #define dstIs32ABGR 1
  242. #include "EffectFilter32.c"
  243. #undef EffectFilter32
  244. #undef srcIs32ABGR
  245. #undef dstIs32ABGR
  246. #endif
  247.  
  248. // --------------------------------------------------------------------------------------
  249. // INTERNAL ROUTINES
  250. //    For clarity/reuse sake, the drawing code is being kept separate from the component
  251. //    interface code.
  252. // --------------------------------------------------------------------------------------
  253.  
  254.  
  255. static OSErr RequestImageFormat(
  256.                                 EffectGlobals*    glob,     // input: globals for rendering
  257.                                 EffectSourcePtr         source,     // input: source to potentially convert
  258.                                 short                    width,        // input: desired width
  259.                                 short                    height,        // input: desired height
  260.                                 OSType                    pixelFormat)// input: desired pixel format (depth & format)
  261. /*
  262.     If the data is already in the requested height and depth, returns.
  263.     Otherwise, calls decompression to get it into the format we can handle
  264. */
  265. {
  266.     OSErr                    err = noErr;
  267.     CDSequenceDataSourcePtr    sourceData = source->source.image;
  268.     ImageDescriptionHandle    curDesc = (ImageDescriptionHandle) sourceData->dataDescription;
  269.     ImageDescriptionHandle    newDesc = nil;
  270.     ImageDescriptionPtr        dp;
  271.  
  272.     dp = *curDesc;
  273.     if (
  274.         (source->effectType == kEffectRawSource) && 
  275.         ( ((dp->cType == kRawCodecType) && (dp->depth == (short)pixelFormat)) || ( dp->cType == pixelFormat) ) &&
  276.  
  277.         (dp->width == width) && 
  278.         (dp->height == height))
  279.     {
  280.         /* already got what we need */
  281.         return noErr;
  282.     }
  283.  
  284.     // otherwise, call the ICM to convert to desired data format
  285.     newDesc = (ImageDescriptionHandle) NewHandleClear(sizeof(ImageDescription));
  286.     err = MemError();
  287.  
  288.     if (err == noErr)
  289.     {
  290.         short pixelSize = QTGetPixelSize(pixelFormat);
  291.  
  292.  
  293.  
  294.         dp = *newDesc;
  295. #if ! NON_MAC_PIXEL_FORMATS
  296.  
  297.         if ((pixelFormat >> 24) != 0) {
  298.  
  299.             // non-Mac format
  300.  
  301.             dp->cType             = pixelFormat;
  302.  
  303.             dp->depth             = pixelSize;
  304.  
  305.         } else     {
  306.  
  307.             dp->cType             = kRawCodecType;
  308.  
  309.             dp->depth             = pixelFormat;
  310.  
  311.         }
  312.  
  313. #else
  314.  
  315.         dp->cType             = pixelFormat;
  316.  
  317.         dp->depth             = pixelSize;
  318.  
  319. #endif
  320.  
  321.         dp->width  = width;
  322.         dp->height = height;
  323.         dp->clutID = -1;
  324.         
  325.         /* the source is a stacked effect - or one in a format we can't handle. */
  326.         /* pass it off to the Generic Effect to convert */
  327.         /* it to a normal source */
  328.         err = ImageCodecEffectConvertEffectSourceToFormat(glob->target, source, newDesc);
  329.  
  330.         if (newDesc)
  331.         {
  332.             DisposeHandle((Handle) newDesc);
  333.         }
  334.     }
  335.  
  336.     return err;
  337.     
  338. } // RequestImageFormat
  339.  
  340. // --------------------------------------------------------------------------------------
  341. static long BlitterPreflight(BlitGlobals    *glob,     // input: globals for rendering
  342.                              short            width,     // input: width of data
  343.                              short            height, // input: height of data
  344.                              long            *depth)    // input/output: depth of data
  345. {
  346.     // *** CHANGE *** If your effect handles different bit depths, change this code to return
  347.     // what bit depths you want.
  348.     
  349.     // our blitter can handle 16 and 32 bit deep -- otherwise, we request a change to 16 bit
  350.     switch (*depth)
  351.     {
  352.         case 16:
  353.         case 32:
  354.             break;
  355.         
  356.         default:
  357.             *depth = 16;
  358.             break;
  359.     }
  360.     // *** END CHANGE ***
  361.  
  362.     // save away the actual depth we are running at
  363.     glob->width     = width;
  364.     glob->height    = height;    
  365.     glob->destDepth = *depth;
  366.     
  367.     return noErr;
  368.     
  369. } // BlitterPreflight
  370.  
  371. // --------------------------------------------------------------------------------------
  372. static long BlitterSetSource(EffectGlobals                *glob,             // input: our globals
  373.                              long                         sourceNumber,    // input: source index to set
  374.                              EffectSourcePtr            source)            // input: source value
  375. {
  376.     OSErr    err = noErr;
  377.  
  378.     if (sourceNumber >= kMaxSources)
  379.     {
  380.         // too many sources for us to handle
  381.         err = -1;
  382.     }
  383.     else
  384.     { 
  385.         // a source we can handle, save it away
  386.         err = RequestImageFormat(glob, source, glob->blitter.width, glob->blitter.height, glob->blitter.dstPixelFormat);
  387.         if (err == noErr)
  388.         {
  389.             glob->blitter.sources[sourceNumber].src = source->source.image;
  390.         }
  391.         else
  392.         {
  393.             glob->blitter.sources[sourceNumber].src = nil;
  394.         }
  395.     }
  396.         
  397.     return (err);
  398.     
  399. } // BlitterSetSource
  400.  
  401.  
  402. // --------------------------------------------------------------------------------------
  403. static long BlitterSetDest(BlitGlobals    *glob,         // input: our globals
  404.                            PixMap        *dstPixMap, // input: pixels we will draw into
  405.                            Rect            *dstRect)    // input: area of pixels we will draw into
  406. {
  407.     OSErr    result = noErr;
  408.     long    offsetH,offsetV;
  409.     char    *baseAddr;
  410.     OSType                dstPixelFormat;
  411.  
  412.  
  413.  
  414.     dstPixelFormat = GETPIXMAPPIXELFORMAT(dstPixMap);
  415.  
  416.     
  417.  
  418.     glob->dstPixelFormat = dstPixelFormat;
  419.  
  420.  
  421.  
  422.  
  423.     // *** CHANGE *** If your effect handles different bit depths, change this code
  424.     /* adjust the destination baseaddress to be at the beginning of the desired rect */
  425.     offsetH = (dstRect->left - dstPixMap->bounds.left);
  426.     if (dstPixMap->pixelSize == 16)
  427.     {
  428.         offsetH <<= 1;                    /* 1 pixel = 2 bytes */
  429.     }
  430.     else
  431.     {
  432.         if (dstPixMap->pixelSize == 32)
  433.         {
  434.             offsetH <<= 2;                    /* 1 pixel = 4 bytes */
  435.         }
  436.         else
  437.         {
  438.             result = -1;                    /* a data format we can't handle */
  439.         }
  440.     }
  441.     // *** END CHANGE ***
  442.     
  443.     offsetV = (dstRect->top - dstPixMap->bounds.top) * dstPixMap->rowBytes;
  444.     baseAddr = dstPixMap->baseAddr + offsetH + offsetV;
  445.  
  446.     glob->dstBaseAddr = baseAddr;
  447.     glob->dstRowBytes = dstPixMap->rowBytes;
  448.  
  449.     return result;
  450.     
  451. } // BlitterSetDest
  452.  
  453.  
  454. // --------------------------------------------------------------------------------------
  455. static long BlitterRenderFrame(BlitGlobals    *glob)        // input: our globals
  456. {
  457.     SInt8            mmuMode;
  458.  
  459.     // render with proper memory mode
  460.     mmuMode = true32b;
  461.     SwapMMUMode(&mmuMode);
  462.     
  463.     // convert data into base/size
  464.     {
  465.         short    i;
  466.         
  467.         for (i = 0; i < kMaxSources; ++i)
  468.         {
  469.             if (glob->sources[i].src)
  470.             {
  471.                 glob->sources[i].srcBaseAddr = glob->sources[i].src->dataPtr;
  472.                 glob->sources[i].srcRowBytes = glob->sources[i].src->dataSize / glob->height;
  473.             }
  474.         }
  475.     }
  476.         
  477.     // *** CHANGE *** If your effect handles different bit depths, write other bit depth routines and
  478.     // call them from here
  479.     
  480.     // do the actual render
  481.     switch (glob->dstPixelFormat)
  482.     {
  483.         case k32ARGBPixelFormat:
  484.             EffectFilter32ARGB(glob);
  485.             break;
  486. #if NON_MAC_PIXEL_FORMATS
  487.         case k32ABGRPixelFormat:
  488.             EffectFilter32ABGR(glob); break;
  489.         case k32BGRAPixelFormat:     // we know how to do these pixel formats
  490.             EffectFilter32BGRA(glob); break;
  491.         case k32RGBAPixelFormat:
  492.             EffectFilter32RGBA(glob); break;
  493. #endif
  494.         case k16BE555PixelFormat:
  495.             EffectFilter16BE555(glob);
  496.             break;
  497. #if NON_MAC_PIXEL_FORMATS
  498.         case k16LE565PixelFormat:
  499.             EffectFilter16LE565(glob); break;
  500.         case k16LE555PixelFormat:
  501.             EffectFilter16LE555(glob); break;
  502. #endif
  503.     }
  504.     // *** END CHANGE ***
  505.  
  506.     SwapMMUMode(&mmuMode);
  507.     
  508.     return noErr;
  509.     
  510. } // BlitterRenderFrame
  511.  
  512.  
  513. // --------------------------------------------------------------------------------------
  514. // COMPONENT ENTRY POINTS
  515. // --------------------------------------------------------------------------------------
  516.  
  517.  
  518. #define kNumPixelFormatsSupported 0x20
  519.  
  520. pascal ComponentResult EffectsFrameOpen(EffectGlobals        *glob,    // input/output: our globals
  521.                                        ComponentInstance    self)    // input: reference to ourself
  522. /*
  523.     This is called once per instance of our component.  Allocate our storage at
  524.     this point.  If we have any shared storage, we would check here to make sure
  525.     it exists, else create it.
  526. */
  527. {
  528.     ComponentResult    result;
  529.     
  530.     result = noErr;
  531.         
  532.     // first, allocate our local storage
  533.     if ((glob = (EffectGlobals*) NewPtrClear(sizeof(EffectGlobals)))==nil)
  534.     {
  535.         result = MemError();
  536.         goto bail;
  537.     }
  538.     
  539.     SetComponentInstanceStorage(self, (Handle) glob);
  540.     
  541.     // we are ourselves, and the current top of chain is us
  542.     glob->self = self;
  543.     glob->target = self;
  544.     glob->wantedDestinationPixelTypeH = (OSType **) NewHandleClear(sizeof(OSType) * (kNumPixelFormatsSupported + 1));
  545.     
  546.     // open the generic effect, this will handle effects we can't handle ourselves
  547.     result = OpenADefaultComponent(decompressorComponentType, kEffectGenericType, &glob->delegate);
  548.     if (result)
  549.         goto bail;
  550.         
  551.     // set up the target for the components below us
  552.     EffectsFrameTarget(glob, self);
  553.  
  554. bail:
  555.     return(result);
  556.     
  557. } // EffectsFrameOpen
  558.  
  559.  
  560. // --------------------------------------------------------------------------------------
  561. // Called each time an instance of our component is going away.  Toss anything we allocated.
  562. pascal ComponentResult EffectsFrameClose(EffectGlobals        *glob,    // input: our globals
  563.                                         ComponentInstance    self)    // input: reference to ourself
  564. {
  565. #pragma unused (self)
  566.  
  567.     if (glob)
  568.     {
  569.         /*     *** CHANGE *** DISPOSE OF YOUR TWEENERS */
  570.         DisposeTweenRecord(&glob->percentage);
  571.  
  572.         /* *** END CHANGE *** */
  573.  
  574.  
  575.  
  576.         DisposeTweenGlobals(&glob->tweenGlobals);
  577.  
  578.         CloseComponent(glob->delegate);
  579.  
  580.  
  581.         DisposeHandle((Handle) glob->wantedDestinationPixelTypeH);
  582.  
  583.  
  584.         DisposePtr((Ptr) glob);
  585.     }
  586.     return(noErr);
  587.     
  588. } // EffectsFrameClose
  589.  
  590.  
  591. // --------------------------------------------------------------------------------------
  592.  
  593. pascal ComponentResult EffectsFrameTarget(EffectGlobals        *glob,    // input: our globals
  594.                                           ComponentInstance target)    // input: reference to new top of chain
  595. /*
  596.     Called when there is a new top of the calling chain.  Remember that ourselves, and tell
  597.     those below us as well.
  598. */
  599. {
  600.     // remember who is top of chain
  601.     glob->target = target;
  602.     
  603.     // and tell folks below us, too.
  604.     ComponentSetTarget(glob->delegate, target);
  605.     
  606.     return(noErr);
  607.     
  608. } // EffectsFrameTarget
  609.  
  610.  
  611. // --------------------------------------------------------------------------------------
  612.  
  613. pascal ComponentResult EffectsFrameVersion(EffectGlobals    *glob)        // input: our globals
  614. /*
  615.     Called to obtain the version of our component.
  616. */
  617. {
  618. #pragma unused (glob)
  619.     
  620.     return kDimmerEffectVersion;
  621.     
  622. } // EffectsFrameVersion
  623.  
  624.  
  625. // --------------------------------------------------------------------------------------
  626. //    Called to prepare for a sequence of frames.  
  627. //    Return in p->capabilities anything in particular your effect requires, such as 
  628. //    limitations on bitdepth.
  629. pascal long EffectsFrameEffectSetup(EffectGlobals            *glob,     // input: our globals
  630.                                      CodecDecompressParams    *p)        // input: information about the thing being decompressed
  631.  
  632. {
  633.     CodecCapabilities     *capabilities = p->capabilities;
  634.     OSErr                err;
  635.     OSType                 *formats = *glob->wantedDestinationPixelTypeH;
  636.     long                wantedPixelSize = capabilities->wantedPixelSize;
  637.     OSType                dstPixelFormat;
  638.     
  639.     dstPixelFormat = GETPIXMAPPIXELFORMAT(&p->dstPixMap);
  640.  
  641.     
  642.  
  643.     switch (dstPixelFormat)
  644.     {
  645.         case k32ARGBPixelFormat:
  646.         case k16BE555PixelFormat:
  647. #if NON_MAC_PIXEL_FORMATS
  648.         case k32BGRAPixelFormat:     // we know how to do these pixel formats
  649.         case k32ABGRPixelFormat:
  650.         case k32RGBAPixelFormat:
  651.         case k16LE565PixelFormat:
  652.         case k16LE555PixelFormat:
  653. #endif
  654.             *formats++ = dstPixelFormat;
  655.             break;
  656.         default:                    // we prefer 16 over 32
  657. #if NON_MAC_PIXEL_FORMATS
  658.             *formats++ = k16LE555PixelFormat;
  659.             *formats++ = k16LE565PixelFormat;
  660.             *formats++ = k32BGRAPixelFormat;
  661.             *formats++ = k32RGBAPixelFormat;
  662.             *formats++ = k32ABGRPixelFormat;
  663. #endif
  664.             *formats++ = k16BE555PixelFormat;
  665.             *formats++ = k32ARGBPixelFormat;
  666.             break;
  667.     }
  668.  
  669.  
  670.  
  671.     // NOTE: 0 marks the end of the format list
  672.  
  673.     *formats++ = 0;
  674.  
  675.  
  676.     /* set up our blitter */
  677.     err = BlitterPreflight(&glob->blitter,
  678.                            (*p->imageDescription)->width,
  679.                            (*p->imageDescription)->height,
  680.                            &wantedPixelSize);
  681.     
  682.     capabilities->wantedPixelSize = 0;
  683.  
  684.     p->wantedDestinationPixelTypes = glob->wantedDestinationPixelTypeH;
  685.  
  686.  
  687.     return (err);
  688.     
  689. } // EffectsFrameEffectSetup
  690.  
  691. // --------------------------------------------------------------------------------------
  692.  
  693. //    Called for each frame, before the request to actually draw
  694. pascal long EffectsFrameEffectBegin(EffectGlobals            *glob,    // input: our globals
  695.                              CodecDecompressParams    *p,     // input: info about frame being drawn
  696.                              EffectsFrameParamsPtr    effect)    // input: info about this effect frame
  697. {
  698.     OSErr                    err = noErr;
  699.     EffectSourcePtr            source;
  700.     long                    numSources = 0;
  701.     wide                    percentage;
  702.  
  703.     #if kMaxAsyncFrames > 0
  704.         /* we can go async if we don't already have an effect scheduled */
  705.         if (glob->asyncCount < kMaxAsyncFrames)
  706.         {
  707.             glob->asyncCount++;
  708.             effect->doAsync = true;
  709.         }
  710.     #endif
  711.  
  712.     // dest changed? 
  713.     if (p->conditionFlags & 
  714.             (codecConditionNewClut+codecConditionFirstFrame+codecConditionNewDepth+codecConditionNewDestination+codecConditionNewTransform))
  715.     {
  716.         // re-scan the sources
  717.         glob->majorSourceChangeSeed = 0;
  718.  
  719.         // re-read the parameters
  720.         glob->frameNumber = 0;
  721.  
  722.         err = BlitterSetDest(&glob->blitter, &p->dstPixMap, &p->dstRect);
  723.         if (err != noErr)
  724.             goto bail;
  725.  
  726.     }
  727.  
  728.     // new sources?  make note of them!
  729.     if (p->majorSourceChangeSeed != glob->majorSourceChangeSeed)
  730.     {
  731.         // grab start of input chain for this effect
  732.         source = effect->source;
  733.  
  734.         /* we can play with up to kMaxSources sources, so go get them */
  735.         while (source != nil && numSources < kMaxSources)
  736.         {        
  737.             /* now give that source to our blitter */
  738.             err = BlitterSetSource(glob, numSources, source);
  739.             if (err != noErr)
  740.                 goto bail;
  741.                 
  742.             source = source->next;
  743.             ++numSources;
  744.         }
  745.  
  746.  
  747.  
  748.         glob->majorSourceChangeSeed = p->majorSourceChangeSeed;
  749.     }
  750.     
  751.     /* if this is a new frame, or the same frame with a new length, get rid of our old parameters & tweeners */    
  752.     if ((effect->frameTime.frameNumber != glob->frameNumber) || (effect->frameTime.virtualDuration != glob->virtualDuration) )
  753.     {
  754.         /*     *** CHANGE *** DISPOSE OF YOUR TWEENERS */
  755.         DisposeTweenRecord(&glob->percentage);
  756.         
  757.         /* *** END CHANGE *** */
  758.  
  759.  
  760.  
  761.         DisposeTweenGlobals(&glob->tweenGlobals);
  762.  
  763.         glob->initialized = false;
  764.         glob->frameNumber = effect->frameTime.frameNumber;
  765.         glob->virtualDuration = effect->frameTime.virtualDuration;
  766.     }
  767.  
  768.     // Read in effect parameters
  769.     if (!glob->initialized)
  770.     {
  771.         Ptr                     data = p->data;
  772.         OSErr                    err;
  773.         long                    index = 1;
  774.         
  775.         err = InitializeTweenGlobals(&glob->tweenGlobals, p);
  776.         if (err!=noErr)
  777.             goto bail;
  778.             
  779.         /*     *** CHANGE *** TIME TO READ IN PARAMETERS TO YOUR EFFECT:
  780.             You can read any number of atoms you wish from the container.  For example, you might have a 
  781.             'star' (start) and 'end ' (end) value.  They might be expressed as percentages, numbers, or other values.
  782.             Or, you might have multiple atoms of type 'para' (param) which would be read in by calling
  783.             QTFindChildByIndex with various index values.  If you want to know how many parameters of a given
  784.             type there are, call QTCountChildrenOfType.  These parameters are specific to your particular effect,
  785.             and will need to be placed there by whoever is authoring the title.
  786.             
  787.             If you require parameters, and they aren't there, return an error.  If you can default the values
  788.             if they are missing, do so and continue.  In general, I'd recommend having a default case unless
  789.             you really are unable to implement it for a technical reason.
  790.             
  791.             These parameters are those that apply to the effect itself.  Later, we'll translate some of these parameters
  792.             into how they relate to *where* in the effect we are.  For example, an effect that runs from a starting
  793.             percentage of 10 to an ending percentage of 90 will have 10 and 90 as parameters here.
  794.         */
  795.         
  796.         /* make our tweener, return if we already have it */
  797.         err = CreateTweenRecord(&glob->tweenGlobals, &glob->percentage, 
  798.                         kParameterUsagePercent, 1, 
  799.                         sizeof(Fixed), kTweenTypeFixed, (void*)0, (void*)fixed1,  
  800.                         effect->frameTime.virtualDuration);
  801.         if (err!=noErr)
  802.             goto bail;
  803.                         
  804.  
  805.  
  806.         /* *** END CHANGE *** */
  807.  
  808.  
  809.  
  810.         glob->initialized = true;
  811.     }
  812.     
  813.     /* determine the amount we are along the tween via the current time - start time */
  814.     percentage = effect->frameTime.value;
  815.     CompSub(&effect->frameTime.virtualStartTime, &percentage);
  816.         
  817.     
  818.     /*     Tween our parameters and get the current value for this frame, prepare to render
  819.         it when the RenderFrame happens. */
  820.     if (err == noErr)
  821.         {
  822.         Fixed    thePercentage;
  823.         
  824.         /* ***** CHANGE TO TWEEN YOUR EFFECTS PARAMETERS */
  825.         
  826.         if (glob->percentage.tween)
  827.             QTDoTween(glob->percentage.tween, percentage.lo, glob->percentage.tweenData, nil, nil, nil );
  828.         
  829.         thePercentage = **(Fixed**)(glob->percentage.tweenData);
  830.         // If we are before the half-way point of this transition, we should
  831.         // be fading the first source to black
  832.         if (thePercentage < fixed1/2)
  833.         {
  834.             (glob->blitter).direction = 1;
  835.             (glob->blitter).dimValue = FixedToInt(FixMul(IntToFixed(512), thePercentage));
  836.         }
  837.         // Otherwise, we are fading up onto the new source
  838.         else
  839.         {
  840.             (glob->blitter).direction = 0;
  841.             (glob->blitter).dimValue = FixedToInt(FixMul(IntToFixed(512), thePercentage)) - 255;
  842.         }
  843.  
  844.         /* ***** END CHANGE */
  845.         }
  846.  
  847.     if (glob->tweenGlobals.atLeastOneTweener)
  848.         {
  849.         // this effect runs constantly
  850.         p->needUpdateOnTimeChange = true;
  851.         p->needUpdateOnSourceChange = false;
  852.         }
  853.     else
  854.         {
  855.         // this effect only needs to run when the sources actually change
  856.         p->needUpdateOnTimeChange = false;
  857.         p->needUpdateOnSourceChange = true;
  858.         }
  859.     
  860.         
  861. // EXCEPTION HANDLING
  862. bail:
  863.     #if kMaxAsyncFrames > 0
  864.         // if we didn't queue the frame, then remove it from used list
  865.         if (err != noErr)
  866.             glob->asyncCount--;
  867.     #endif
  868.     
  869.     return err;
  870.     
  871. } // EffectsFrameEffectBegin
  872.  
  873.  
  874. // --------------------------------------------------------------------------------------
  875. pascal long EffectsFrameEffectRenderFrame(EffectGlobals             *glob,         // input: our globals
  876.                                     EffectsFrameParamsPtr    effect)        // input: effect frame to be rendered
  877. /*
  878.     Start rendering of the given frame.
  879. */
  880. {
  881. #pragma unused (effect)
  882.  
  883.     /* render the frame */
  884.     BlitterRenderFrame(&glob->blitter);
  885.     
  886.     #if kMaxAsyncFrames > 0
  887.         glob->asyncCount--;
  888.     #endif
  889.  
  890.     return noErr;
  891.     
  892. } // EffectsFrameEffectRenderFrame
  893.  
  894.  
  895. // --------------------------------------------------------------------------------------
  896. pascal long EffectsFrameEffectCancel(EffectGlobals            *glob,         // input: our globals
  897.                                     EffectsFrameParamsPtr    effect)        // input: effect frame to be canceled
  898. /*
  899.     Halt rendering of the given frame, even if it is only partially completed.
  900. */
  901. {
  902. #pragma unused (effect)
  903. #pragma unused (glob)
  904.  
  905.     #if kMaxAsyncFrames > 0
  906.         glob->asyncCount--;
  907.     #endif
  908.  
  909.     return noErr;
  910.     
  911. } // EffectsFrameEffectCancel
  912.  
  913.  
  914. // ----------------------------------------------------------------------------------------
  915.  
  916. pascal ComponentResult EffectsFrameGetCodecInfo(EffectGlobals    *glob,
  917.                                                 CodecInfo        *info)
  918. /*
  919.  *    CDGetCodecInfo allows us to return information about ourselves to the codec manager.
  920.  *    
  921.  *    There will be a tool for determining appropriate values for the accuracy, speed
  922.  *    and level information. For now we estimate with scientific wild guessing.
  923.  *
  924.  *  The info is stored as a resource in the same file with our component.
  925.  */
  926. {
  927.     OSErr err = noErr;
  928.  
  929.     if (info == nil)
  930.     {
  931.         err = paramErr;
  932.     }
  933.     else
  934.     {
  935.         CodecInfo **tempCodecInfo;
  936.  
  937.         err = GetComponentResource((Component) glob->self,
  938.                                    codecInfoResourceType,
  939.                                    kEffectcdciRes,
  940.                                    (Handle *) &tempCodecInfo);
  941.         if (err == noErr)
  942.         {
  943.             *info = **tempCodecInfo;
  944.             DisposeHandle((Handle) tempCodecInfo);
  945.         }
  946.     }
  947.  
  948.     return err;
  949.     
  950. } // EffectsFrameGetCodecInfo
  951.  
  952.  
  953. // ---------------------------------------------------------------------------------------------------------------------------
  954. pascal ComponentResult EffectsFrameGetParameterListHandle(EffectGlobals    *glob,        // input: our globals
  955.                                                          Handle            *theHandle)    // output: the parameter description for this effect
  956. {
  957.     OSErr                    err = noErr;
  958.     
  959.     err = GetComponentResource((Component) glob->self,
  960.                                FOUR_CHAR_CODE('atms'),
  961.                                kEffectatmsRes,
  962.                                theHandle);
  963.     
  964.     return(err);
  965.     
  966. } // EffectsFrameGetParameterListHandle
  967.  
  968. // ----------------------------------------------------------------------------------------
  969. pascal long EffectsFrameEffectGetSpeed(EffectGlobals * glob, QTAtomContainer parameters, Fixed *pFPS)
  970. {
  971. #pragma unused (glob, parameters)
  972.  
  973.     if (pFPS)
  974.         *pFPS = IntToFixed(30);
  975.         
  976.     return noErr;
  977.     
  978. } // EffectsFrameEffectGetSpeed
  979.  
  980.  
  981.